//	@title			Virt-Manager Go API
//	@version		1.0
//	@description	A modern RESTful API for managing KVM/QEMU virtual machines built on libvirt
//	@termsOfService	http://swagger.io/terms/

//	@contact.name	API Support
//	@contact.url	http://www.swagger.io/support
//	@contact.email	support@swagger.io

//	@license.name	Apache 2.0
//	@license.url	http://www.apache.org/licenses/LICENSE-2.0.html

//	@host		localhost:8080
//	@BasePath	/api/v1

//	@securityDefinitions.apikey	ApiKeyAuth
//	@in							header
//	@name						Authorization

package main

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	_ "github.com/yourusername/virt-manager-go/docs" // Import swagger docs
	"github.com/yourusername/virt-manager-go/internal/api"
	"github.com/yourusername/virt-manager-go/internal/config"
	"github.com/yourusername/virt-manager-go/internal/service"
)

var (
	version = "1.0.0"
	log     = logrus.New()
)

func main() {
	// Initialize logger
	log.SetFormatter(&logrus.JSONFormatter{})
	log.SetLevel(logrus.InfoLevel)
	log.SetOutput(os.Stdout)

	log.WithField("version", version).Info("Starting virt-manager-go API server")

	// Load configuration
	cfg, err := config.Load("configs/config.yaml")
	if err != nil {
		log.WithError(err).Fatal("Failed to load configuration")
	}

	// Initialize connection manager
	connMgr := service.NewConnectionManager(log)
	// Initialize console handler
	// Create service instances first
	serialProxy := service.NewSerialProxy(connMgr, log)
	graphicsProxy := service.NewGraphicsProxy(connMgr, log)

	// Auto-connect to default URI if configured
	if cfg.Libvirt.AutoConnect {
		log.WithField("uri", cfg.Libvirt.DefaultURI).Info("Auto-connecting to default libvirt URI")

		if err := connMgr.AddConnection("default", cfg.Libvirt.DefaultURI); err != nil {
			log.WithError(err).Fatal("Failed to connect to default libvirt URI")
		}

		if err := connMgr.SetDefaultConnection("default"); err != nil {
			log.WithError(err).Fatal("Failed to set default connection")
		}

		log.Info("Successfully connected to libvirt")
	} else {
		log.Info("Auto-connect disabled, use API to add connections")
	}

	// Set Gin mode
	if cfg.Server.Mode == "release" {
		gin.SetMode(gin.ReleaseMode)
	}

	// Create router
	router := api.NewRouter(connMgr, serialProxy, graphicsProxy, log)
	addr := fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port)

	// Create HTTP server
	srv := &http.Server{
		Addr:           addr,
		Handler:        router,
		ReadTimeout:    time.Duration(cfg.Server.ReadTimeout) * time.Second,
		WriteTimeout:   time.Duration(cfg.Server.WriteTimeout) * time.Second,
		MaxHeaderBytes: 1 << 20,
	}

	// Start server in goroutine
	go func() {
		log.WithFields(logrus.Fields{
			"host": cfg.Server.Host,
			"port": cfg.Server.Port,
		}).Info("API server listening")

		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.WithError(err).Fatal("Failed to start server")
		}
	}()

	log.WithField("address", addr).Info("Server started successfully")
	log.Info("API documentation: http://" + addr + "/swagger/index.html")
	log.Info("Health check: http://" + addr + "/health")

	// Wait for interrupt signal
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	log.Info("Shutting down server...")

	// Graceful shutdown with timeout
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	if err := srv.Shutdown(ctx); err != nil {
		log.WithError(err).Fatal("Server forced to shutdown")
	}

	if err := serialProxy.CloseAll(); err != nil {
		log.WithError(err).Warn("Error closing serial proxies")
	}
	if err := graphicsProxy.CloseAll(); err != nil {
		log.WithError(err).Warn("Error closing graphics proxies")
	}
	// Close all connections
	if err := connMgr.CloseAll(); err != nil {
		log.WithError(err).Warn("Error closing connections")
	}

	log.Info("Server exited gracefully")
}
